from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager
from flask_login import LoginManager
from flask_restx import Api
from werkzeug.exceptions import HTTPException
from .core import make_response
from .config import get_config


db = SQLAlchemy()
jwt = JWTManager()
login_manager = LoginManager()


@login_manager.request_loader
def load_user_from_request(_request):
	# 不通过请求自动登录（JWT 负责认证），返回 None 即可
	return None


def create_app(env: str = None) -> Flask:
	app = Flask(__name__)
	app.config.from_object(get_config(env))

	# Init extensions
	db.init_app(app)
	jwt.init_app(app)
	login_manager.init_app(app)

	# Flask-Login requirements: user_loader
	from .models.user import User

	@login_manager.user_loader
	def load_user(user_id: str):
		try:
			return User.query.get(int(user_id))
		except Exception:
			return None

	# Optional: allow using current_user with JWT-Extended
	from flask_jwt_extended import current_user as jwt_current_user  # noqa: F401

	@jwt.user_lookup_loader
	def user_lookup_callback(_jwt_header, jwt_data):
		identity = jwt_data.get("sub")
		try:
			return User.query.get(int(identity))
		except Exception:
			return None

	# 未授权统一返回 JSON
	from flask import jsonify

	@login_manager.unauthorized_handler
	def unauthorized_handler():
		return jsonify({"message": "未授权"}), 401

	# RESTX Api with Swagger
	api = Api(
		app,
		title="Flask RBAC API",
		description="Flask RBAC API with JWT Access/Refresh Token",
		version="0.0.1",
		doc="/", # SwaggerUI Endpoint
		errors=False
	)

	# Register namespaces lazily to avoid circular imports
	from .api.users import api as users_ns
	from .api.articles import api as articles_ns
	from .api.auth import api as auth_ns

	api.add_namespace(auth_ns, path="/auth")
	api.add_namespace(users_ns, path="/users")
	api.add_namespace(articles_ns, path="/articles")

	# Shell context
	@app.shell_context_processor
	def make_shell_context():
		from .models.user import User
		from .models.article import Article
		return {"db": db, "User": User, "Article": Article}

	# Register global error handlers for this app
	register_error_handlers(app)

	return app


# Global error handlers to ensure code/msg/data JSON
@jwt.unauthorized_loader
def _jwt_unauthorized_callback(reason):
	return make_response(None, 401, reason)


@jwt.invalid_token_loader
def _jwt_invalid_callback(reason):
	return make_response(None, 422, reason)


@jwt.expired_token_loader
def _jwt_expired_callback(jwt_header, jwt_payload):
	return make_response(None, 401, "Token 已过期")


def register_error_handlers(app: Flask):
	@app.errorhandler(HTTPException)
	def handle_http_exception(e: HTTPException):
		code = e.code or 500
		message = e.description or e.name or "HTTP Error"
		return make_response(None, code, message)

	@app.errorhandler(Exception)
	def handle_exception(e: Exception):
		return make_response(None, 500, "服务器内部错误")


# Register handlers for the created app instances
_app_for_handlers = create_app if 'create_app' in globals() else None


